package main

import (
	"context"
	"fmt"
	"sync"
	"time"
)

var start time.Time
var foods chan string

func cook(ctx context.Context, name string) {
	for {
		select {
		case <-ctx.Done():
			fmt.Printf("%7.4f 厨师 %s: 下班了\n", time.Now().Sub(start).Seconds(), name)
			return
		default:
			time.Sleep(time.Second * 3)
			fmt.Printf("%7.4f 厨师 %s: 做了十个 包子\n", time.Now().Sub(start).Seconds(), name)
			for i := 0; i < 10; i++ {
				foods <- "包子"
			}
		}
	}
}

func eat(ctx context.Context, name string) {
	for {
		select {
		case i := <-foods:
			if i == "" {
				fmt.Printf("%7.4f 顾客 %s: 离开了\n", time.Now().Sub(start).Seconds(), name)
				return
			}
			time.Sleep(time.Second * 1)
			fmt.Printf("%7.4f 顾客 %s: 吃了一个 %s\n", time.Now().Sub(start).Seconds(), name, i)
		}
	}
}

func main() {
	start = time.Now()
	foods = make(chan string, 30)
	cooks := [...]string{"老张", "老李"}
	customers := [...]string{"花花", "小明", "娜娜", "小刘", "阿牛", "宝宝"}
	ctx, cancel := context.WithCancel(context.Background())

	var wgCooks sync.WaitGroup
	for _, c := range cooks {
		wgCooks.Add(1)
		go func(name string) {
			defer wgCooks.Done()
			cook(ctx, name)
		}(c)
	}

	var wgCustomers sync.WaitGroup
	for _, c := range customers {
		wgCustomers.Add(1)
		go func(name string) {
			defer wgCustomers.Done()
			eat(ctx, name)
		}(c)
	}
	time.Sleep(time.Second * 10)
	fmt.Printf("%7.4f 店长 %s: 打烊了\n", time.Now().Sub(start).Seconds(), "本人")
	cancel()
	wgCooks.Wait()
	close(foods)
	wgCustomers.Wait()
	fmt.Printf("%7.4f 店长 %s: 关门了\n", time.Now().Sub(start).Seconds(), "本人")
}
